home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tcl / tclWinNotify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-24  |  6.6 KB  |  274 lines

  1. /* 
  2.  * tclWinNotify.c --
  3.  *
  4.  *    This file contains Windows-specific procedures for the notifier,
  5.  *    which is the lowest-level part of the Tcl event loop.  This file
  6.  *    works together with ../generic/tclNotify.c.
  7.  *
  8.  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * SCCS: @(#) tclWinNotify.c 1.8 96/02/29 09:19:08
  14.  */
  15.  
  16. #include "tclInt.h"
  17. #include "tclPort.h"
  18. #ifndef STk_CODE
  19. #  include <winsock.h>
  20. #endif
  21.  
  22. /*
  23.  * The following variable is a backdoor for use by Tk.  It is set when
  24.  * Tk needs to process events on the Tcl event queue without reentering
  25.  * the system event loop.  Tk uses it to flush the Tcl event queue.
  26.  */
  27.  
  28. static int ignoreEvents = 0;
  29.  
  30. /*
  31.  *----------------------------------------------------------------------
  32.  *
  33.  * TclWinFlushEvents --
  34.  *
  35.  *    This function is a special purpose hack to allow Tk to
  36.  *    process queued Window events during a recursive event loop
  37.  *    without looking for new events on the system event queue.
  38.  *
  39.  * Results:
  40.  *    None.
  41.  *
  42.  * Side effects:
  43.  *    Services any pending Tcl events and calls idle handlers.
  44.  *
  45.  *----------------------------------------------------------------------
  46.  */
  47.  
  48. void
  49. TclWinFlushEvents()
  50. {
  51.     ignoreEvents = 1;
  52.     while (Tcl_DoOneEvent(TCL_DONT_WAIT|TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS)) {
  53.     }
  54.     ignoreEvents = 0;
  55. }
  56.  
  57. /*
  58.  *----------------------------------------------------------------------
  59.  *
  60.  * Tcl_WatchFile --
  61.  *
  62.  *    Arrange for Tcl_DoOneEvent to include this file in the masks
  63.  *    for the next call to select.  This procedure is invoked by
  64.  *    event sources, which are in turn invoked by Tcl_DoOneEvent
  65.  *    before it invokes select.
  66.  *
  67.  * Results:
  68.  *    None.
  69.  *
  70.  * Side effects:
  71.  *    
  72.  *    The notifier will generate a file event when the I/O channel
  73.  *    given by fd next becomes ready in the way indicated by mask.
  74.  *    If fd is already registered then the old mask will be replaced
  75.  *    with the new one.  Once the event is sent, the notifier will
  76.  *    not send any more events about the fd until the next call to
  77.  *    Tcl_NotifyFile. 
  78.  *
  79.  *----------------------------------------------------------------------
  80.  */
  81.  
  82. void
  83. Tcl_WatchFile(file, mask)
  84.     Tcl_File file;        /* Opaque identifier for a stream. */
  85.     int mask;            /* OR'ed combination of TCL_READABLE,
  86.                  * TCL_WRITABLE, and TCL_EXCEPTION:
  87.                  * indicates conditions to wait for
  88.                  * in select. */
  89. {
  90.     int type;
  91.  
  92.     (void) Tcl_GetFileInfo(file, &type);
  93.  
  94.     if (type == TCL_WIN_SOCKET) {
  95. #ifndef STk_CODE
  96.     TclWinWatchSocket(file, mask);
  97. #endif
  98.     } else if (type == TCL_WIN_FILE) {
  99.     Tcl_Time timeout = { 0, 0 };
  100.  
  101.     /*
  102.      * Files are always ready under Windows, so we just set a
  103.      * 0 timeout.
  104.      */
  105.  
  106.     Tcl_SetMaxBlockTime(&timeout);
  107.     } else if (type == TCL_WIN_PIPE) {
  108.     /*
  109.      * We don't support waiting on pipes yet.
  110.      */
  111.     }
  112. }
  113.  
  114. /*
  115.  *----------------------------------------------------------------------
  116.  *
  117.  * Tcl_FileReady --
  118.  *
  119.  *    Indicates what conditions (readable, writable, etc.) were
  120.  *    present on a file the last time the notifier invoked select.
  121.  *    This procedure is typically invoked by event sources to see
  122.  *    if they should queue events.
  123.  *
  124.  * Results:
  125.  *    The return value is 0 if none of the conditions specified by mask
  126.  *    was true for fd the last time the system checked.  If any of the
  127.  *    conditions were true, then the return value is a mask of those
  128.  *    that were true.
  129.  *
  130.  * Side effects:
  131.  *    None.
  132.  *
  133.  *----------------------------------------------------------------------
  134.  */
  135.  
  136. int
  137. Tcl_FileReady(file, mask)
  138.     Tcl_File file;    /* File handle for a stream. */
  139.     int mask;            /* OR'ed combination of TCL_READABLE,
  140.                  * TCL_WRITABLE, and TCL_EXCEPTION:
  141.                  * indicates conditions caller cares about. */
  142. {
  143.     int type;
  144.  
  145.     (void) Tcl_GetFileInfo(file, &type);
  146.  
  147.     if (type == TCL_WIN_SOCKET) {
  148. #ifndef STk_CODE
  149.     return TclWinSocketReady(file, mask);
  150. #endif
  151.     } else if (type == TCL_WIN_FILE) {
  152.     /*
  153.      * Under Windows, files are always ready, so we just return the
  154.      * mask that was passed in.
  155.      */
  156.  
  157.     return mask;
  158.     }
  159.     return 0;
  160. }
  161.  
  162. /*
  163.  *----------------------------------------------------------------------
  164.  *
  165.  * Tcl_WaitForEvent --
  166.  *
  167.  *    This procedure does the lowest level wait for events in a
  168.  *    platform-specific manner.  It uses information provided by
  169.  *    previous calls to Tcl_WatchFile, plus the timePtr argument,
  170.  *    to determine what to wait for and how long to wait.
  171.  *
  172.  * Results:
  173.  *    The return value is normally TCL_OK.  However, if there are
  174.  *    no events to wait for (e.g. no files and no timers) so that
  175.  *    the procedure would block forever, then it returns TCL_ERROR.
  176.  *
  177.  * Side effects:
  178.  *    May put the process to sleep for a while, depending on timePtr.
  179.  *    When this procedure returns, an event of interest to the application
  180.  *    has probably, but not necessarily, occurred.
  181.  *
  182.  *----------------------------------------------------------------------
  183.  */
  184.  
  185. int
  186. Tcl_WaitForEvent(timePtr)
  187.     Tcl_Time *timePtr;        /* Specifies the maximum amount of time
  188.                  * that this procedure should block before
  189.                  * returning.  The time is given as an
  190.                  * interval, not an absolute wakeup time.
  191.                  * NULL means block forever. */
  192. {
  193.     MSG msg;
  194.     int foundEvent = 1;
  195.  
  196.     /*
  197.      * If we are ignoring events from the system, just return immediately.
  198.      */
  199.  
  200.     if (ignoreEvents) {
  201.     return TCL_OK;
  202.     }
  203.  
  204.     /*
  205.      * Set up the asynchronous select handlers for any sockets we
  206.      * are watching.
  207.      */
  208. #ifndef STk_CODE
  209.     TclWinNotifySocket();
  210. #endif
  211.  
  212.     /*
  213.      * Look for an event, setting a timer so we don't block forever.
  214.      */
  215.  
  216.     if (timePtr != NULL) {
  217.     UINT ms;
  218.     ms = timePtr->sec * 1000;
  219.     ms += timePtr->usec / 1000;
  220.  
  221.     if (ms > 0) {
  222.         UINT timerHandle = SetTimer(NULL, 0, ms, NULL);
  223.         GetMessage(&msg, NULL, 0, 0);
  224.         KillTimer(NULL, timerHandle);
  225.     } else {
  226.  
  227.         /*
  228.          * If the timeout is too small, we just poll.
  229.          */
  230.  
  231.         foundEvent = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  232.     }
  233.     } else {
  234.     GetMessage(&msg, NULL, 0, 0);
  235.     }
  236.  
  237.     /*
  238.      * Dispatch the message, if we found one.  If we are exiting, be
  239.      * sure to inform Tcl so we can clean up properly.
  240.      */
  241.  
  242.     if (foundEvent) {
  243.     if (msg.message == WM_QUIT) {
  244.         Tcl_Exit(0);
  245.     }
  246.     TranslateMessage(&msg);
  247.     DispatchMessage(&msg);
  248.     }
  249.     return TCL_OK;
  250. }
  251.  
  252. /*
  253.  *----------------------------------------------------------------------
  254.  *
  255.  * Tcl_Sleep --
  256.  *
  257.  *    Delay execution for the specified number of milliseconds.
  258.  *
  259.  * Results:
  260.  *    None.
  261.  *
  262.  * Side effects:
  263.  *    Time passes.
  264.  *
  265.  *----------------------------------------------------------------------
  266.  */
  267.  
  268. void
  269. Tcl_Sleep(ms)
  270.     int ms;            /* Number of milliseconds to sleep. */
  271. {
  272.     Sleep(ms);
  273. }
  274.